/*
 * Copyright (c) 2008 by 1eEurope (Switzerland) AG, Thalwil
 *
 * Customer:	1eEurope (Switzerland) AG
 * Project:		BKS
 * Created:		30.09.2008, WBL
 *
*/

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.Configuration;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Text;
using System.Xml.Xsl;
using By1eEurope.BKS.Tools.Utils;
using Microsoft.SharePoint;

namespace By1eEurope.BKS.Controls
{
    /// <summary>
    /// Search control, displaying the search results of a ISearchProvider
    /// </summary>
    public class Search : WebControl
    {
        protected ISearchProvider Provider = null;
        
        protected override void  OnInit(EventArgs e)
        {
 	        // create the provider specified in the config file. If no provider
            // is specified, then create the provider for the Live Search
            if (!string.IsNullOrEmpty(WebConfigurationManager.AppSettings["Search.Provider"]))
            {
                this.Provider = (ISearchProvider)Activator.CreateInstance(
                   Type.GetType(WebConfigurationManager.AppSettings["Search.Provider"]));
            }
            else
                this.Provider = new SharePointAPISearchProvider();
        }

	    private int _resultsPerPage = 10;
        /// <summary>
        /// Results per page, if you use paging
        /// </summary>
        public int ResultsPerPage
        {
            get { return _resultsPerPage; }
            set { _resultsPerPage = value; }
        }

        private int _pageIndex = 0;
        /// <summary>
        /// PageIndex
        /// </summary>
        public int PageIndex
        {
            get
            { 
                int pageIndex = 0;
                if (Int32.TryParse(this.Page.Request.QueryString["PageIndex"],out pageIndex))
                    _pageIndex = pageIndex;
                return _pageIndex;
            }
            set { _pageIndex = value; }
        }

        private string _scope = "";
        /// <summary>
        /// Search scope to query
        /// </summary>
        public string Scope
        {
            get { return _scope; }
            set { _scope = value; }
        }

        private string _queryText = "";
        /// <summary>
        /// Search parameter. First priority has always the GET parameter 'k'. Even if this property is set.
        /// </summary>
        public string QueryText
        {
            get 
            {
                if (!string.IsNullOrEmpty(this.Page.Request.Form["k"]+""))
                    return this.Page.Request.Form["k"]+"";
                if (!string.IsNullOrEmpty(this.Page.Request.QueryString["k"]))
                    return this.Page.Request.QueryString["k"];
                else
                    return _queryText;
            }
            set { _queryText = value; }
        }

        private bool _highlight = false;
        /// <summary>
        /// Enable / disable highlighting of search results
        /// </summary>
        public bool Highlight
        {
            get { return _highlight; }
            set { _highlight = value; }
        }

        private string _highlightBefore = "";
        /// <summary>
        /// Start tag of highlighting
        /// </summary>
        public string HighlightBefore
        {
            get { return _highlightBefore; }
            set { _highlightBefore = value; }
        }

        private string _highlightAfter = "";
        /// <summary>
        /// End tag of highlighting
        /// </summary>
        public string HighlightAfter
        {
            get { return _highlightAfter; }
            set { _highlightAfter = value; }
        }

        private string xsltPath;
        /// <summary>
        /// Path to the XSLT, that receives and tranforms the XML structure to the desired HTML-Output
        /// </summary>
        public string XsltPath
        {
            get { return xsltPath; }
            set { xsltPath = value; }
        }


        protected override void  Render(HtmlTextWriter writer)
        {
 	        SearchResults res = this.Provider.ExecuteQuery(this.QueryText, this.ResultsPerPage, this.PageIndex, this.Highlight, this.HighlightBefore, this.HighlightAfter, this.Scope);
            string xml = SerializeObject(res, typeof(SearchResults));

            XslCompiledTransform xslt = XmlUtil.GetXsltDocument(SPContext.Current.Web, this.xsltPath);
            XsltArgumentList xsltArgs = new XsltArgumentList();
            int topage = Math.Min(this.PageIndex + 5, (int)(((res.TotalResults-1)/this.ResultsPerPage)));
            int frompage = Math.Max(0, this.PageIndex - 5);

            xsltArgs.AddParam("datetime", "", DateTime.Now.ToLongDateString());
            xsltArgs.AddParam("guid", "", Guid.NewGuid().ToString());
            xsltArgs.AddParam("lang", "", SPContext.Current.Web.Locale+"");
            xsltArgs.AddParam("query", "", this.QueryText+"");
            xsltArgs.AddParam("scope", "", this.Scope+"");
            xsltArgs.AddParam("pageindex", "", this.PageIndex+"");
            xsltArgs.AddParam("frompage", "", frompage + "");
            xsltArgs.AddParam("topage", "", topage + "");
            xsltArgs.AddParam("shownext", "", this.PageIndex < (int)(((res.TotalResults - 1) / this.ResultsPerPage)));
            xsltArgs.AddParam("showprev", "", this.PageIndex > 0);
            StringBuilder stringBuilder = XmlUtil.TransformXslt(xslt, xml, xsltArgs);
            writer.Write(stringBuilder.ToString());
        }

        private string SerializeObject(Object pObject, Type t)
        {
            string xmlizedString = null;
            XmlSerializer xs = new XmlSerializer(t);

            MemoryStream memoryStream = new MemoryStream();
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

            xs.Serialize(xmlTextWriter, pObject);
            memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
            xmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
            xmlizedString = xmlizedString.Substring(1);
            return xmlizedString;
        }
        private string UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            String constructedString = encoding.GetString(characters);
            return (constructedString);
        }
    }
}